﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using GeoAPI.Geometries;
using GeoAPI.IO;
using NetTopologySuite.Geometries;
using NetTopologySuite.Features;
using NetTopologySuite.IO;

using SpectationClient.GUI;
using SpectationClient.Stuff;
using SpectationClient.DataBaseDescription;
using System.Xml;

namespace SpectationClient.DGVExtensions {
    public class DataGridViewGeometryCell : DataGridViewTextBoxCell {
        public int srid { get; set; }

        private static WKTWriter WKTWriter = new WKTWriter();
        private static WKBReader WKBReader = new WKBReader();
        private static WKTReader WKTReader = new WKTReader();
        /// <summary>
        /// Get or sets the cell geometry.
        /// </summary>
        public IGeometry Geometry {
            get { return getGeometry(); }
            set { this.Value = value.AsBinary(); }
        }




        /// <summary>
        /// Returns the geometry stored in the cell.
        /// </summary>
        /// <returns></returns>
        private IGeometry getGeometry() {

            IGeometry g = null;

            Object v = this.Value;

            if(v is IGeometry) {
                g = v as IGeometry;
            }

            if(v is Byte[]) {
                try {
                    g = WKBReader.Read(v as Byte[]);
                } catch { }
            }
            if(v is String) {
                String vs = v as String;
                Regex regexWKBHex = new Regex(@"^[0-9A-F]+$");
                Regex regexWKT    = new Regex(@"^(POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+$");
                if(regexWKT.IsMatch(vs)) {
                    g = WKTReader.Read(vs);
                } else if(regexWKBHex.IsMatch(vs)) {
                    g = WKBReader.Read(WKBReader.HexToBytes(vs));
                }
            }

            return g;
        }


        protected override object GetFormattedValue(object value, int rowIndex, ref DataGridViewCellStyle cellStyle, TypeConverter valueTypeConverter, TypeConverter formattedValueTypeConverter, DataGridViewDataErrorContexts context) {
            object mv = String.Empty;
            if(DBNull.Value == value || null == value || value.ToString().Length == 0) {
                mv = DBNull.Value;
            } else {
                IGeometry g;
                if(value is Byte[]) {
                    g = WKBReader.Read(value as Byte[]);
                    mv =  WKTWriter.ToPoint(g.Coordinate);
                } else if(value is String) {
                    mv = value as String;
                }
            }
            return base.GetFormattedValue(mv, rowIndex, ref cellStyle, valueTypeConverter, formattedValueTypeConverter, context);
        }

        public override object ParseFormattedValue(object formattedValue, DataGridViewCellStyle cellStyle, TypeConverter formattedValueTypeConverter, TypeConverter valueTypeConverter) {
            Object mv = null;
            if(formattedValue == DBNull.Value || formattedValue == null || formattedValue.ToString().Trim().Length == 0) {
                mv = DBNull.Value;
            } else {
                IGeometry g = null;
                try {
                    if(formattedValue is String) {
                        g = WKTReader.Read(formattedValue as String);

                    }
                    this.ErrorText = "";
                } catch(Exception ex) {
                    this.ErrorText = ex.Message;
                    this.RaiseDataError(new DataGridViewDataErrorEventArgs(ex, this.ColumnIndex, this.RowIndex, DataGridViewDataErrorContexts.Parsing));

                }

                if(g != null) mv = g.AsBinary();
            }

            return mv;
        }

        protected override bool SetValue(int rowIndex, object value) {

            return base.SetValue(rowIndex, value);
        }
    }
}
